﻿using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Text;
using VLog4net;
using VMathNet.Numerics.LinearAlgebra;
using VT.Framework.Designer.Flow;
using VT.Framework.Designer.Project;

namespace VIA.VTPlatformService
{
    public interface IVTPlatformManager
    {
        VTFlowBlockWrapper? GetBlockWrapper(VTFlowBlockInfo info);
        VTFlowBlockWrapper? GetBlockWrapper(string filePath, int flowIndex);
        VTFlowBlockWrapper? GetBlockWrapper(string filePath, int flowIndex, int projectIndex);
        VTProject? GetProject(string filePath, int projectIndex);
        List<(int count, string filePath)> GetCacheProjectInfo();
        void LoadProject(string filePath, int count);
        void ClearCache();
    }

    public class VTPlatformManager : IVTPlatformManager
    {
        private ILogger _logger;
        private ConcurrentDictionary<(string path, int flowIndex), List<VTFlowBlockWrapper>> _flows = new ConcurrentDictionary<(string path, int flowIndex), List<VTFlowBlockWrapper>>();
        private ConcurrentDictionary<string, List<VTProject>> _projects = new ConcurrentDictionary<string, List<VTProject>>();

        public VTPlatformManager(ILogger<VTPlatformManager> logger)
        {
            _logger = logger;
        }

        public void ClearCache()
        {
            _projects.Clear();
            _flows.Clear();
        }

        public VTFlowBlockWrapper? GetBlockWrapper(VTFlowBlockInfo info)
        {
            return GetBlockWrapper(info.FilePath, info.FlowIndex);
        }

        public VTFlowBlockWrapper? GetBlockWrapper(string filePath, int flowIndex)
        {
            if (!_flows.TryGetValue((filePath, flowIndex), out var vTFlowBlockWraps)) return null;
            var blockWrapper = vTFlowBlockWraps.FirstOrDefault(x => x.IsEnableEvent.WaitOne(0));
            blockWrapper ??= vTFlowBlockWraps.MaxBy(x => x.GetWorkingTime());
            blockWrapper?.Work();
            return blockWrapper;
        }

        public VTFlowBlockWrapper? GetBlockWrapper(string filePath, int flowIndex, int projectIndex)
        {
            if (!_flows.TryGetValue((filePath, flowIndex), out var vTFlowBlockWraps)) return null;
            var blockWrapper = vTFlowBlockWraps.FirstOrDefault(x => x.ProjectId == projectIndex);
            return blockWrapper;
        }

        public void LoadProject(string filePath, int count)
        {
            try
            {
                if (!_projects.TryGetValue(filePath, out var projects))
                {
                    projects = new List<VTProject>();
                    _projects.TryAdd(filePath, projects);
                }
                if (projects.Count == 0)
                {
                    VTProject project = new VTProject();
                    project.LoadAs(filePath);
                    if (project != null)
                    {
                        projects.Add(project);
                    }
                    else throw new Exception($"加载工程失败，工程路径：{filePath}");
                }
                var p0 = projects[0];
                int ct = count - projects.Count;
                for (int i = 0; i < ct; i++)
                {
                    var p1 = new VTProject(p0);
                    projects.Add(p1);
                }

                //_flows.Clear();
                int pojectId = 0;
                foreach (VTProject project in projects)
                {
                    for (int i = 0; i < project.FlowList.Count; i++)
                    {
                        if (!_flows.TryGetValue((filePath, i), out var vTFlowBlockWrappers))
                        {
                            vTFlowBlockWrappers = new List<VTFlowBlockWrapper>();
                            _flows.TryAdd((filePath, i), vTFlowBlockWrappers);
                        }
                        vTFlowBlockWrappers.Add(new(project.FlowList[i].FlowBlock, pojectId));
                    }
                    pojectId++;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
            }
        }

        public List<(int count, string filePath)> GetCacheProjectInfo()
        {
            List<(int count, string filePath)> infos = new List<(int count, string filePath)>();
            foreach (var item in _projects)
            {
                infos.Add((item.Value.Count, item.Key));
            }
            return infos;
        }

        public VTProject? GetProject(string filePath, int projectIndex)
        {
            if (string.IsNullOrEmpty(filePath)) return null;
            if (!_projects.TryGetValue(filePath, out var projects)) return null;
            if (projects == null || projects.Count < projectIndex + 1) return null;
            return projects[projectIndex];
        }
    }
}
